import { useEffect, useRef } from "react";
function Sortable(id, props) {
  const listRef = useRef(null);
  const pos = useRef({});
  const moveRef = useRef(null);
  const cloneRef = useRef(null);
  const getNodes = () => {
    const nodes = listRef.current.children;
    return nodes;
  };
  const initHelper = (current) => {
    if (!current) return null;
    let clone = current.cloneNode(true);
    const cloneNode = listRef.current.appendChild(clone);
    const { top, left, height, width } = current.getBoundingClientRect();
    cloneNode.style.position = "fixed";
    cloneNode.style.top = top + "px";
    cloneNode.style.left = left + "px";
    cloneNode.style.width = width + "px";
    cloneNode.style.height = height + "px";
    return cloneNode;
  };

  const mousedownListener = (e) => {
    e.preventDefault();
    pos.current = { x: e.pageX, y: e.pageY };
    if (e.target.parentElement) {
      moveRef.current = e.target.parentElement;
    }
  };
  const css = (el, prop, val) => {
    let style = el && el.style;

    if (style) {
      if (val === void 0) {
        if (document.defaultView && document.defaultView.getComputedStyle) {
          val = document.defaultView.getComputedStyle(el, "");
        } else if (el.currentStyle) {
          val = el.currentStyle;
        }

        return prop === void 0 ? val : val[prop];
      } else {
        if (!(prop in style) && prop.indexOf("webkit") === -1) {
          prop = "-webkit-" + prop;
        }

        style[prop] = val + (typeof val === "string" ? "" : "px");
      }
    }
  };
  const animate = (target, transitionY) => {
    css(target, "transform", "");
    css(target, "transition", "");
    css(target, "transform", `translate3d(0px,${transitionY}px,0)`);

    target.offsetWidth;
    css(target, "transition", "transform 0.15s");
    css(target, "transform", `translate3d(0px,0px,0)`);
    if (typeof target.animated === "number") {
      clearTimeout(target.animated);
      css(target, "transform", "");
      css(target, "transition", "");
      target.isActivity = false;
    }
    target.timerOut = setTimeout(() => {
      css(target, "transform", "");
      css(target, "transition", "");
      target.isActivity = false;
    }, 0.15 * 1000);
  };
  const swapElements = (a, b) => {
    if (a === b) return;
    //记录父元素
    var bp = b.parentNode,
      ap = a.parentNode;
    //记录下一个同级元素
    var an = a.nextElementSibling,
      bn = b.nextElementSibling;
    //如果参照物是邻近元素则直接调整位置
    if (an === b) return bp.insertBefore(b, a);
    if (bn === a) return ap.insertBefore(a, b);
    if (a.contains(b))
      //如果a包含了b
      return ap.insertBefore(b, a), bp.insertBefore(a, bn);
    else return bp.insertBefore(a, b), ap.insertBefore(b, an);
  };
  const move = () => {
    let _nodes = getNodes();
    for (let i = 0; i < _nodes.length; i++) {
      let item = _nodes[i];
      if (item === moveRef.current) continue;
      const cloneReact = cloneRef.current.getBoundingClientRect();
      const itemReact = item.getBoundingClientRect();

      if (
        cloneReact.top + cloneReact.height >
          itemReact.top + itemReact.height / 2 &&
        cloneReact.top + cloneReact.height < itemReact.top + itemReact.height &&
        !item.isActivity
      ) {
        item.isActivity = true;
        swapElements(moveRef.current, item);
        const newItemRact = moveRef.current.getBoundingClientRect();
        const currentNodeRact = item.getBoundingClientRect();
        const moveY = newItemRact.top - currentNodeRact.top;
        animate(item, moveY);
        animate(moveRef.current, -moveY);
      }
    }
  };
  const mousemoveListener = (e) => {
    if (!moveRef?.current) return;

    const { x, y } = pos.current;
    let mouseMove = {
      x: e.pageX - x,
      y: e.pageY - y,
    };

    if (Math.abs(mouseMove.x) > 5 || Math.abs(mouseMove.y) > 5) {
      if (!cloneRef?.current) {
        cloneRef.current = initHelper(moveRef.current);
        moveRef.current.style.opacity = 0;
        moveRef.current.style.visibility = "hidden";
      } else {
        move();
        cloneRef.current.style.transform = `translate3d(${mouseMove.x}px,${mouseMove.y}px,0)`;
      }
    }
  };
  const removeNode = (node) => {
    if (node?.parentElement !== null) {
      node.parentElement.removeChild(node);
    }
  };
  const getListId = () => {
    let listId = [];
    let nodes = getNodes();
    for (let i = 0; i < nodes.length; i++) {
      const item = nodes[i];
      listId.push(item?.dataset?.id);
    }
    return listId;
  };
  const mouseupListener = (e) => {
    if (cloneRef?.current) {
      removeNode(cloneRef?.current);
      cloneRef.current = null;
      moveRef.current.style.opacity = 1;
      moveRef.current.style.visibility = "visible";
      moveRef.current = null;
      props?.onChange && props.onChange(getListId());
    }
  };
  useEffect(() => {
    listRef.current = document.getElementById(id);
    const $dom = listRef?.current;
    if ($dom) {
      $dom.addEventListener("mousedown", mousedownListener);
      $dom.addEventListener("mousemove", mousemoveListener);
      $dom.addEventListener("mouseup", mouseupListener);
    }
    return () => {
      if ($dom) {
        $dom.removeEventListener("mousedown", mousedownListener);
        $dom.removeEventListener("mousemove", mousemoveListener);
        $dom.removeEventListener("mouseup", mouseupListener);
      }
    };
  }, [id]);
}
export default Sortable;
